﻿using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Runtime.InteropServices;
using System.Threading;

namespace Hsenl.Network {
    // 来自 ChatGPT, 运行后会每秒打印当前进程各线程的 CPU 利用率
    public class ThreadCpuUsageMonitor {
        // 用来存储线程上次CPU时间的快照
        private readonly Dictionary<int, TimeSpan> _lastCpuTimes = new();
        private readonly Dictionary<int, TimeSpan> _lastSnapshot = new();

        // 监控间隔
        private readonly TimeSpan _interval = TimeSpan.FromSeconds(1);

        public static void Start() {
            var thread = new Thread(() => {
                ThreadCpuUsageMonitor monitor = new();
                monitor.Run();
            }) {
                IsBackground = true,
                Name = "ThreadCpuUsageMonitor Worker"
            };
            thread.Start();
        }

        public void Run() {
            Console.WriteLine("Starting thread CPU usage monitor...");
            while (true) {
                this.SampleAndPrint();
                Thread.Sleep(this._interval);
            }
        }

        private void SampleAndPrint() {
            var current = Process.GetCurrentProcess();

            var threadInfos = new List<(int Id, double CpuPercent)>();

            foreach (ProcessThread thread in current.Threads) {
                try {
                    int tid = thread.Id;
                    TimeSpan totalCpu = thread.TotalProcessorTime;

                    if (this._lastCpuTimes.TryGetValue(tid, out var lastCpu)) {
                        double cpuUsed = (totalCpu - lastCpu).TotalMilliseconds;
                        double cpuPercent = cpuUsed / (this._interval.TotalMilliseconds * Environment.ProcessorCount) * 100;
                        threadInfos.Add((tid, cpuPercent));
                    }

                    this._lastCpuTimes[tid] = totalCpu;
                }
                catch {
                    // 线程可能已经退出，忽略
                }
            }

            Console.Clear();
            Console.WriteLine($"Thread CPU usage over last {this._interval.TotalSeconds}s:");
            Console.WriteLine($"{"TID",6} | {"CPU %",6}");
            Console.WriteLine(new string('-', 20));
            foreach (var info in threadInfos.OrderByDescending(t => t.CpuPercent).Take(20)) {
                Console.WriteLine($"{info.Id,6} | {info.CpuPercent,6:F2}");
            }
        }

        [DllImport("kernel32.dll")]
        public static extern int GetCurrentThreadId();
    }
}